package com.gitee.feizns.web.utils;

import lombok.SneakyThrows;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author feizns
 * @since 2019/7/23
 */
public abstract class DateUtils {

    /**
     * 一天的毫秒数
     */
    public static final long ONE_DAY_MILLIS_SECOND = TimeUnit.DAYS.toMillis(1);

    /**
     * 第一秒的格式
     */
    private static final String FIRST_SECOND_PATTERN = "yyyy-MM-dd 00:00:00";

    /**
     * 最后一秒的格式
     */
    private static final String LAST_SECOND_PATTERN = "yyyy-MM-dd 23:59:59";

    /**
     * yyyy-MM-dd HH:mm:ss
     */
    private static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    /**
     * yyyy-MM
     */
    private static final String YYYY_MM = "yyyy-MM";

    /**
     * 格式化日期
     * @param date
     * @param pattern
     * @return
     */
    public static final String format(Date date, String pattern) {
        return new SimpleDateFormat(pattern).format(date);
    }

    /**
     * 解析日期
     * @param date
     * @param pattern
     * @return
     */
    public static final Date parse(String date, String pattern) {
        try {
            return new SimpleDateFormat(pattern).parse(date);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 格式今天日期
     * @param pattern
     * @return
     */
    public static final String formatNow(String pattern) {
        return format(new Date(), pattern);
    }

    /**
     * 添加一天
     * @param date
     * @return
     */
    public static final Date plusDay(Date date) {
        return plusDay(date, 1);
    }

    /**
     * 添加指定天
     * @param date
     * @param day
     * @return
     */
    public static final Date plusDay(Date date, int day) {
        long time = date.getTime();
        for (int i = 0; i < day; i++)
            time += ONE_DAY_MILLIS_SECOND;
        return new Date(time);
    }

    /**
     * 减去一天
     * @param date
     * @return
     */
    public static final Date minusDay(Date date) {
        return minusDay(date, 1);
    }

    /**
     * 减去指定天
     * @param date
     * @param day
     * @return
     */
    public static final Date minusDay(Date date, int day) {
        long time = date.getTime();
        for (int i = 0; i < day; i++)
            time -= ONE_DAY_MILLIS_SECOND;
        return new Date(time);
    }

    /**
     * 获取两个日期之间的所有天
     * @param startTime
     * @param endTime
     * @return
     */
    public static final List<Date> getDays(Date startTime, Date endTime) {
        long start = startTime.getTime();
        long end = endTime.getTime();
        List<Date> ret = new ArrayList<>();
        while ( start <= end ) {
            ret.add(new Date(start));
            start += ONE_DAY_MILLIS_SECOND;
        }
        return ret;
    }

    /**
     * 获取天的第一秒
     * @param date
     * @return
     */
    public static final Date getFirstSecondOfDay(Date date) {
        return parse(format(date, FIRST_SECOND_PATTERN), FIRST_SECOND_PATTERN);
    }

    /**
     * 获取一天中的最后秒
     * @param date
     * @return
     */
    public static final Date getLastSecondOfDay(Date date) {
        return parse(format(date, LAST_SECOND_PATTERN), YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * 获取两个日期的所有月份
     * @param start
     * @param end
     * @return
     */
    @SneakyThrows
    public static List<Date> getBetweenMonths(Date start, Date end) {
        List<Date> ret = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat(YYYY_MM);
        int startYear = getYear(start);
        int startMonth = getMonth(start);
        int endYear = getYear(end);
        int endMonth = getMonth(end);

        do {
            ret.add(sdf.parse(startYear + "-" + (startMonth + 1)));
            startMonth += 1;
            if ( startMonth == 12 ) {
                startMonth = 0;
                startYear += 1;
            }
        } while ( startYear <= endYear && startMonth <= endMonth );

        return ret;
    }

    /**
     * 获取年份
     * @param date
     * @return
     */
    public static int getYear(Date date) {
        return get(date, Calendar.YEAR);
    }

    /**
     * 获取月份
     * @param date
     * @return
     */
    public static int getMonth(Date date) {
        return get(date, Calendar.MONTH);
    }

    /**
     * 指定类型的值
     * @param date
     * @param calendarField
     * @return
     */
    public static int get(Date date, int calendarField) {
        Calendar ret = Calendar.getInstance();
        ret.setTime(date);
        return ret.get(calendarField);
    }

}
